﻿/******************************************************************************
* File description: animationController_Purify.cpp
* Function: 纯化动画Controller，基于State的状态，根据时间计算当前动画的过渡状态，并提供获取当前状态的接口
* Current Version: 1.0.0
* Author: JNN
* Date: 2025-07-01
*  -----
*  Copyright by 博坤生物 .
 *****************************************************************************/

#include "animationController_Purify.h"

extern QQmlApplicationEngine* gQmlEngine;
/** @brief 构造函数 */
AnimationController_Purify::AnimationController_Purify(AnimationState_Purify* state) : _state(state)
{

    if(_state == nullptr){
        return;
    }

    _syringePercent.resize(_state->_syringeNum);
    _syringePercentEnd.resize(_state->_syringeNum);
    _syringePercentSpeed.resize(_state->_syringeNum);

    connect(_state, SIGNAL(sigReset()), this, SLOT(on_reset()));
    connect(_state, SIGNAL(sigWheelChanged(int, int, double, int)), this, SLOT(on_wheelChanged(int, int, double, int)));
    connect(_state, SIGNAL(sigHatPushed()), this, SLOT(on_hatPushed()));
    connect(_state, SIGNAL(sigHatPressed()), this, SLOT(on_hatPressed()));
    connect(_state, SIGNAL(sigValveChanged(int, bool, bool)), this, SLOT(on_valveChanged(int, bool, bool)));
    connect(_state, SIGNAL(sigSyringeChanged(int, double, double, double)), this, SLOT(on_syringeChanged(int, double, double, double)));
    connect(_state, SIGNAL(sigLiquidChanged(QMap<QString, QVector<int>>)), this, SLOT(on_liquidChanged(QMap<QString, QVector<int>>)));

    on_reset();

    // 阀门不参与复位
    _valveAngle.clear();
    _valveEnd.clear();
    for(int i = 0; i < _state->_valveNum; i ++){
        _valveAngle.push_back(0);
        _valveEnd.push_back(0);
    }

    _commObject = new AnimationCommObject_Purify;

    gQmlEngine->setObjectOwnership(_commObject, QQmlApplicationEngine::CppOwnership);

}

/** @brief 开启计时器（动画帧每帧调用） */
void AnimationController_Purify::startTimer(){


    _timer = new QTimer();
    _timer->setInterval(_interval);
//    _timer->setInterval(1000);
    connect(_timer, SIGNAL(timeout()), this, SLOT(updateState()));
    _timer->start();


    _timer_e = new QElapsedTimer;
    _timer_e->start();

}

/** @brief 停止计时器 */
void AnimationController_Purify::stopTimer(){
    if(_timer){
        _timer->stop();
        delete _timer;
    }
    if(_timer_e){
        delete _timer_e;
    }
}


/** @brief 析构函数 */
AnimationController_Purify::~AnimationController_Purify(){
    if(_timer)      {   delete _timer;        _timer = nullptr;         }
    if(_commObject) {   delete _commObject;   _commObject = nullptr;    }
}

/** @brief QML调用请求动画信息(自定义组件传递数据版本)
 *  @return AnimationCommObject_Purify 返回每个组件的位置 */
AnimationCommObject_Purify* AnimationController_Purify::requestInfo_object(){

//    if(_commObject) {
//        delete _commObject;
//        _commObject = nullptr;
//    }
//    _commObject = new AnimationCommObject_Purify;

    QTime timer;
    timer.start();
    int lastTime = 0;

    if(!_commObject){
        qDebug() << "[ERROR] CommObject=nullptr";
        return nullptr;
    }

    // 转盘&盖盖
    _commObject->_wheelPosi =  _wheel;
    _commObject->_hatNum =     _state->_hatNum;
    _commObject->_pressPosi =  _hatPressPosi;
    _commObject->_pushPosi =   _hatPushPosi;


    lastTime = timer.elapsed();

    // 瓶帽状态
    _commObject->_bottleHasHat = _bottleHasHat;

    // 注射器液体
    _commObject->_syringePercentage = _syringePercent;

    // 注射器是否正在推
    _commObject->_syringeIsPushing = _syringeIsPushing;

    // 注射器颜色
    _commObject->_syringeColor = _state->_syringeColor;

    // 阀门状态
    _commObject->_valveAngle = _valveAngle;


    lastTime = timer.elapsed();

    // 速率(上面标注的那个)
    _commObject->_syringeSpeed1.clear();
    _commObject->_syringeSpeed2.clear();
    _commObject->_syringeSpeed1.reserve(10);
    _commObject->_syringeSpeed2.reserve(10);
    for(int i = 0; i < _state->_syringeNum; i ++){
        if(i < _state->_syringeSpeed_target.size()){
            if(_state->_speedUnit == 0){
                _commObject->_syringeSpeed1.push_back(_state->_syringeSpeed_target[i]);
            }else{
                _commObject->_syringeSpeed1.push_back(SyringeCalculator::speedS2min(i, _state->_syringeSpeed_target[i]));
            }
        }if(i < _state->_syringeSpeed_realtime.size()){
            if(_state->_speedUnit == 0){
                _commObject->_syringeSpeed2.push_back(_state->_syringeSpeed_realtime[i]);
            }else{
                _commObject->_syringeSpeed2.push_back(SyringeCalculator::speedS2min(i, _state->_syringeSpeed_realtime[i]));
            }
        }
    }

    // 色谱柱
    _commObject->_particlePosi = _particle;

    // 检测器
    _commObject->_detectorGlowVisible = _state->_detector;
    _commObject->_detectorGlowAngle = _detectorAngle;

    // 加热
    _commObject->_heatingState = _state->_heatingState;

    lastTime = timer.elapsed();

    // 注射器尺码
    _commObject->_syringeWidth.clear();
    _commObject->_syringeHeight.clear();
    _commObject->_syringeHeight.push_back(30.0/150.0);
    for(int i = 0; i < _state->_syringeNum; i ++){
        _commObject->_syringeHeight.push_back(SyringeCalculator::getSyringeHeightMM(i+1) / 220);
    }
    _commObject->_syringeWidth.push_back(30.0/350.0);
    for(int i = 0; i < _state->_syringeNum; ++ i){
        _commObject->_syringeWidth.push_back(SyringeCalculator::getSyringeDiameterMM(i+1) / 440);
    }

    _commObject->_gCollectContainer = _state->_gCollectContainer;
    _commObject->_pPumpState = _state->_pPumpState;

    // 液路
    _commObject->_liquidState = _state->_pipeGraph->getLiquidState();
    _commObject->_liquidFlowState = _state->_pipeGraph->getLiquidFlowState();

    return _commObject;
}

/** @brief QML调用请求动画信息
 *  @return QVariantMap 返回每个组件的位置 */
QVariantMap AnimationController_Purify::requestInfo(){

    QVariantMap res;

    // 转盘&盖盖
    res["WheelPosi"] =  _wheel;
    res["HatNum"] =     _state->_hatNum;
    res["PressPosi"] =  _hatPressPosi;
    res["PushPosi"] =   _hatPushPosi;

    // 瓶帽状态
    QVariantList bhl;
    foreach(bool has, _bottleHasHat){
        bhl.push_back(has);
    }
    res["BottleHasHat"] = bhl;

    // 注射器液体
    QVariantList sp;
    foreach(double percent, _syringePercent){
        sp.push_back(percent);
    }res["SyringePercentage"] = sp;

    QVariantList sip;
    foreach(bool isPushing, _syringeIsPushing){
        sip.push_back(isPushing);
    }
    res["SyringeIsPushing"] = sip;

    // 注射器颜色
    QVariantList cl;
    foreach(QColor color, _state->_syringeColor){
        cl.push_back(color);
    }res["SyringeColor"] = cl;

    // 阀门状态
    QVariantList va;
    foreach(double angle, _valveAngle){
        va.push_back(angle);
    }res["ValveAngle"] = va;

    // 液体路径
//    QVariantList pl;
//    foreach(stLiquidPath path, _pathList){
//        QVariantMap mp;
//        QVariantList vl;
//        foreach(int v, path.vertex){
//            vl.push_back(v);
//        }mp["path"] = vl;
//        mp["pathStart"] = path.start;
//        mp["pathEnd"] = path.end;
//        mp["pathColor"] = path.color;
//        pl.push_back(mp);
//    }
//    res["PathList"] = pl;
//    res["LiquidState"] = _state->_pipeGraph->getLiquidState();


    // 速率(上面标注的那个)
    QVariantList ss1, ss2;
    for(int i = 0; i < _state->_syringeNum; i ++){
        if(i < _state->_syringeSpeed_target.size()){
            if(_state->_speedUnit == 0){
                ss1.push_back(_state->_syringeSpeed_target[i]);
            }else{
                ss1.push_back(SyringeCalculator::speedS2min(i, _state->_syringeSpeed_target[i]));
            }
        }if(i < _state->_syringeSpeed_realtime.size()){
            if(_state->_speedUnit == 0){
                ss2.push_back(_state->_syringeSpeed_realtime[i]);
            }else{
                ss2.push_back(SyringeCalculator::speedS2min(i, _state->_syringeSpeed_realtime[i]));
            }
        }
    }
    res["SyringeSpeed1"] = ss1;
    res["SyringeSpeed2"] = ss2;

    // 色谱柱
    QVariantList ps;
    for(int i = 0; i < _particleNum; i ++){
        ps.push_back(_particle[i]);
    }
    res["ParticlePosi"] = ps;

    // 检测器
    res["DetectorGlowVisible"] = _state->_detector;
    res["DetectorGlowAngle"] = _detectorAngle;

    // 加热
    res["HeatingState"] = _state->_heatingState;

    // 注射器尺码
    QVariantList syrHeight;
    QVariantList syrWidth;
    syrHeight.push_back(30.0/150.0);
    for(int i = 0; i < _state->_syringeNum; i ++){
        syrHeight.push_back(SyringeCalculator::getSyringeHeightMM(i+1) / 220);
    }
    syrWidth.push_back(30.0/350.0);
    for(int i = 0; i < _state->_syringeNum; ++ i){
        syrWidth.push_back(SyringeCalculator::getSyringeDiameterMM(i+1) / 440);
    }
    res["SyringeHeight"] = syrHeight;
    res["SyringeWidth"] = syrWidth;

    res["gCollectContainer"] = _state->_gCollectContainer;
    res["PPumpState"] = _state->_pPumpState;

    res["PipeArrow"] = QStringList();

    return res;
}

/** @brief 把转盘位置置于[0, 转盘孔位数]之间。例如传入12，转盘有9个孔，则12实际上代表的是孔3
 *  @param posi 转盘位置
 *  @param base 孔位数
 *  @return double 实际的转盘位置*/
double normWheelPosi(double posi, int base){
    if(base <= 0){
        return 0;
    }
    while(posi > base){
        posi -= base;
    }while(posi < 0){
        posi += base;
    }
    return posi;
}

/** @brief 更新 */
void AnimationController_Purify::updateState(double interval){

//    QElapsedTimer timer;
//    timer.start();
    _state->_pipeGraph->updateLiquidPath();
//    qDebug() << "计算液路总时间" << timer.elapsed() << "ms";

    _interval_real = _timer_e->elapsed() - _lastTime;
    _lastTime = _timer_e->elapsed();


    // 注射器
    double speedBase;
    if(interval == -1){
        speedBase = _interval_real / 1000.0;
    }else{
        speedBase = 100;
    }
    _syringeIsPushing.clear();
    for(int i = 0; i < _state->_syringeNum; i ++){
        // 这里controller和state的speed写重复了，后续再改
//        if(i<_state->_syringeSpeed_realtime.size()) _state->_syringeSpeed_realtime[i] = _state->_syringeSpeed_target[i];
        if(_syringePercent[i] > _syringePercentEnd[i]){             // 向下推
            _syringePercent[i] = std::max(_syringePercent[i]-_syringePercentSpeed[i]*speedBase, _syringePercentEnd[i]);
            _state->setVertexEmitting(i, true);
            _syringeIsPushing.push_back(1);
        }else if(_syringePercent[i] < _syringePercentEnd[i]){       // 向上推
            _syringePercent[i] = std::min(_syringePercent[i]+_syringePercentSpeed[i]*speedBase, _syringePercentEnd[i]);
            _state->setVertexEmitting(i, false);
            _syringeIsPushing.push_back(-1);
        }else{
//            if(i<_state->_syringeSpeed_realtime.size()) _state->_syringeSpeed_realtime[i] = 0;
            _state->setVertexEmitting(i, false);
            _syringeIsPushing.push_back(0);
        }
    }

    // 转盘
    if(interval == -1){
        speedBase = 0.08;
    }else{
        speedBase = 1;
    }
    if(_wheel != _wheelEnd){
        _wheel = normWheelPosi(_wheel + _wheelSpeed*_wheelDirect*speedBase, _state->_wheelNum);
    }
    if(std::fabs(_wheel-_wheelEnd) < _wheelSpeed*speedBase ||
       std::fabs(_wheel+_state->_wheelNum-_wheelEnd < _wheelSpeed*speedBase) ||
       std::fabs(_wheel-(_wheelEnd+_state->_wheelNum)) < _wheelSpeed*speedBase){
        _wheel = _wheelEnd;
    }
//    qDebug() << "当前转盘位置:" << _wheel;

    // 推瓶盖
    if(_hatPushState == 0){
        _hatPushPosi = _hatPushPosi - 0.08;
        _hatPushPosi = std::max(0.0, _hatPushPosi);
    }else if(_hatPushState == 1){
        _hatPushPosi = _hatPushPosi + 0.08;
        if(_hatPushPosi >= 1){
            _hatPushState = 0;
        }
    }
//    if(_hatPushPosi < 0.1 && _hatPushPosi > 0 && _hatPushState == 0){    // 往回拉快拉到头时触发压瓶盖
//        _hatPressState = 1;
//    }         // 修改为压瓶盖需要手动触发……


    // 压瓶盖
    if(_hatPressState == 0){
        _hatPressPosi = _hatPressPosi - 0.08;
        _hatPressPosi = std::max(0.0, _hatPressPosi);
    }else if(_hatPressState == 1){
        _hatPressPosi = _hatPressPosi + 0.08;
        if(_hatPressPosi >= 1){
            _hatPressState = 0;
        }
    }if(_hatPressPosi < 0.1 && _hatPressPosi > 0 && _hatPressState == 0){
        if(std::floor(_state->_wheelPosi) < _bottleHasHat.size()){
            _bottleHasHat[std::floor(_state->_wheelPosi)] = true;
        }else{
            qDebug() << "ERROR: [Class]AnimationController_Purify [Func]UpdateState - _wheelPosi out-of-range ->" << std::floor(_state->_wheelPosi);
        }
    }

//    // 更新液体流动状态
//    QStringList removeList;
//    speedBase = 0.001;
//    for(auto iter = _pathList.begin(); iter != _pathList.end(); iter ++){
//        iter.value().end = std::min(iter.value().end+speedBase, 2.0);
//        if(!iter.value().state){
//            iter.value().start = std::min(iter.value().start+speedBase, 2.0);
//            if(iter.value().start == 2){
//                removeList.push_back(iter.key());
//            }
//        }
//    }
//    foreach(QString key, removeList){
//        _pathList.remove(key);
//    }

    // [TODO] 这里液体流动改为直接从pipeGraph里面获取
    // 我这代码写的啥玩意 这都是从哪调的呀………………


    // 阀门
    for(int i = 0; i < _valveAngle.size(); i ++){
        if(_valveAngle[i] < _valveEnd[i]){
            _valveAngle[i] += 0.08;
        }else if(_valveAngle[i] > _valveEnd[i]){
            _valveAngle[i] -= 0.08;
        }
        if(std::fabs(_valveAngle[i]-_valveEnd[i])<0.04){
            _valveAngle[i] = _valveEnd[i];
        }
    }

    // 色谱柱
    // 判断有没有液体流动
    bool columnLiquid = false;
    foreach(QString key, _pathList.keys()){
        if(key.contains("7->20") && _pathList[key].state){
            columnLiquid = true;
        }
    }
    // 色谱柱粒子绘制
    if(interval == -1){
        speedBase = 0.018;
    }else{
        speedBase = 1;
    }
    for(int i = 0; i < _particleNum; i ++){
        if(_particle[i] < 1.1){
            _particle[i] += _particle_speed[i] * speedBase;
        }else if(_particle[i] >= 1.1){
            if(_state->_column && columnLiquid){
                _particle[i] = -0.3;
            }
        }
    }

    // 检测器
    if(interval == -1){
        speedBase = 1;
    }else{
        speedBase = 0.07;
    }
    _detectorAngle += speedBase;
    if(_detectorAngle >= 2*3.1415926){
        _detectorAngle = 0;
    }

}

/** @brief 急停（已弃用） */
void AnimationController_Purify::crashStop(){

    if(!_state){
        return;
    }
    // 暂时只急停注射器的
    for(int i = 0; i < _state->_syringeNum; i ++){
        if(_syringePercent.size()<=i || _syringePercentEnd.size()<=i){
            break;
        }
        _syringePercentEnd[i] = _syringePercent[i];
        if(_state->_syringePercentage.size() <= i){
            break;
        }
        _state->_syringePercentage[i] = _syringePercent[i];
    }
}


/** @brief 复位 */
void AnimationController_Purify::on_reset(){


    // 阀门不参与复位
//    _valveAngle.clear();
//    _valveEnd.clear();
//    for(int i = 0; i < _state->_valveNum; i ++){
//        _valveAngle.push_back(0);
//        _valveEnd.push_back(0);
//    }

    _bottleHasHat.clear();
    for(int i = 0; i < _state->_wheelNum; i ++){
        _bottleHasHat.push_back(false);
    }

    _syringePercent.clear();
    _syringePercentEnd.clear();
    _syringePercentSpeed.clear();
    for(int i = 0; i < _state->_syringeNum; i ++){
        _syringePercent.push_back(_state->_syringePercentage[i]);
        _syringePercentEnd.push_back(_state->_syringePercentage[i]);
        _syringePercentSpeed.push_back(0);
    }


    _wheel = 0;
    _wheelEnd = 0;
    _wheelSpeed = 0;
    _wheelDirect = 0;

    _hatPressPosi = 0;
    _hatPressState = 0;
    _hatPushPosi = 0;
    _hatPushState = 0;

    _particle.clear();
    for(int i  = 0; i < _particleNum; i ++){
        _particle.push_back(1.2);
    }

}

/** @brief 推盖 */
void AnimationController_Purify::on_hatPushed(){
//    qDebug() << "Controller触发推盖";
    _hatPushState = 1;
}
/** @brief 盖盖 */
void AnimationController_Purify::on_hatPressed(){
//    qDebug() << "Controller触发压盖";
    _hatPressState = 1;
}

/** @brief 阀门变化
 *  @param idx 阀门编号
 *  @param state1 当前状态
 *  @param state2 要转到的状态 */
void AnimationController_Purify::on_valveChanged(int idx, bool state1, bool state2){
    _valveAngle[idx] = state1 ? 0.5 : 0;
    _valveEnd[idx] = state2 ? 0.5 : 0;
}

/** @brief 阀门变化
 *  @param idx 阀门编号
 *  @param state1 当前状态
 *  @param state2 要转到的状态 */
void AnimationController_Purify::on_syringeChanged(int idx, double percentage1, double percentage2, double speed){


//    qDebug() << "注射器变更" << idx << percentage1 << percentage2 << speed;

    if(_refreshPosi){
        _syringePercent[idx] = percentage1;
    }
    _syringePercentEnd[idx] = percentage2;
    _syringePercentSpeed[idx] = speed;
}

/** @brief 转盘变化
 *  @param posi1 当前状态
 *  @param posi2 要转到的状态
 *  @param speed 速度
 *  @param direct 方向*/
void AnimationController_Purify::on_wheelChanged(int posi1, int posi2, double speed, int direct){
    if(_refreshPosi){
        _wheel = posi1;
    }
    _wheelEnd = posi2;
    _wheelSpeed = speed;
    _wheelDirect = direct;
}

/** @brief 流的液体状态变化
 *  @param pathList 液体路径 */
void AnimationController_Purify::on_liquidChanged(QMap<QString, QVector<int>> pathList){

    QSet<QString> keySet;
    for(auto iter = pathList.begin(); iter!=pathList.end(); iter ++){
        keySet.insert(iter.key());
    }for(auto iter = _pathList.begin(); iter != _pathList.end(); iter ++){
        keySet.insert(iter.key());
    }

    foreach(QString key, keySet){
        if(pathList.contains(key) && _pathList.contains(key)){      // 液体保持流动
            continue;
        }if(pathList.contains(key) && !_pathList.contains(key)){    // 增加新的液体路径
            if(pathList[key].size() <= 0)  continue;
            // 颜色计算
            int firstIdx = pathList[key][0];
            QColor pathColor;
            if(firstIdx >= 0 && firstIdx < _state->_syringeColor.size()){
                pathColor = _state->_syringeColor[firstIdx];
            }else{
                pathColor = QColor(188, 188, 188);
            }
            // 增加新路径
            _pathList[key] = stLiquidPath(pathList[key], 0, 0, pathColor, true);
        }if(!pathList.contains(key) && _pathList.contains(key)){    // 删除液体路径
            _pathList[key].state = false;
        }
    }


}
